package net.sf.calibur.transport;

import net.sf.calibur.msgbuf.CommandFactory;
import net.sf.calibur.engine.CaliburEngine;
import net.sf.calibur.transport.message.CommandMessage;
import net.sf.calibur.transport.message.Message;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SessionManager {
	public final static String ATTR_SESSION = "session";
	public final static String ATTR_MESSAGE_RECEIVER = "message_receiver";

	private Logger logger = LoggerFactory.getLogger(getClass());
	private CommandFactory commandFactory;
	private CaliburEngine engine;

	public SessionManager(CaliburEngine engine,
			CommandFactory messageBeanFactory) {
		this.engine = engine;
		this.commandFactory = messageBeanFactory;
	}

	public CommandFactory getCommandFactory() {
		return commandFactory;
	}

	public void sessionConnected(Session session) throws Exception {
		// 把session当前state设置为connected
		session.setState(SessionState.CONNECTED);

		// 调用当前state的connected方法（此处是发送session握手信息）
		session.getState().connected(session);
	}

	public void sessionClosed(Session session) {
		SessionState state = getSessionState(session);
		if (state != null) {
			state.closed(session);
		}
	}
	
	public void exceptionCaught(Session session, Throwable cause) {
		SessionState state = getSessionState(session);
		if (state != null) {
			state.exceptionCaught(session, cause);
		} else {
			logger.warn("Delayed exception on closed session.", cause);
		}
	}

	private SessionState getSessionState(Session session) {
		return session == null ? null : session.getState();
	}

	public void messageReceived(Session session, Message message) {
		session.getState().messageReceived(session, message);
	}

	public void sessionIdle(Session session) {
		session.getState().idle(session);
	}

	public void onCommandMessage(Session session, CommandMessage cm) {
		CommandMessageEvent cme = new CommandMessageEvent(cm, session);
		if (logger.isDebugEnabled()) {
			logger.debug(String.format("Received command %d input argument: %s",
					cm.getCommandId(), cm.getInput().toString()));
		}
		engine.addEvent(cme);
	}

	public void sessionLost(Session session, Throwable cause) {
		engine.addEvent(new SessionLostEvent(session, cause));
	}
}
